#include "command.h"
#include "taskQueue.h"
#include "virDir.h"
#include <myHeader.h>
#include <mysql/mysql.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
char *dirStart="/home/sun/wd/ex";
bool flag=false;
int getHash(char *fileName,char *hash){
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    char buf[1024*1024];
    
    int fd=open(fileName,O_RDWR);
    lseek(fd,0,SEEK_SET);
    while(1){
        memset(buf,0,1024*1024);
        ssize_t sret=read(fd,buf,sizeof(buf));
        if(sret==0){
            break;
        }
        SHA1_Update(&ctx,buf,sret);
    }
    unsigned char md[20]={0};
    SHA1_Final(md,&ctx);
    char sha1str[41]={0};
    for(int i=0;i<20;++i){
        char temp[3]={0};
        sprintf(temp,"%02X",md[i]);
        strcat(sha1str,temp);
    }
    strcpy(hash,sha1str);
    return 0;
}

int MySQLSentence(sqlType type,MYSQL *mysql,char *argv1,char *argv2,char *argv3){
    mysql_query(mysql,"use netDisk;");
    char sentence[1024];
    switch(type){
    case SELECT:
        sprintf(sentence,"SELECT %s FROM %s WHERE BINARY %s;\n",argv1,argv2,argv3);
        if (mysql_query(mysql, sentence) != 0) {
            printf("查询失败\n");
            fprintf(stderr, "mysql_query 失败: %s\n", mysql_error(mysql));
            // exit(1);
        } 
        break;
    case INSERT:
        sprintf(sentence,"INSERT INTO %s %s VALUES %s;\n",argv1,argv2,argv3);
        if (mysql_query(mysql, sentence) != 0) {
            fprintf(stderr, "插入失败: %s\n", mysql_error(mysql));
        } else {
        }
        break;
    case DELETE:
        sprintf(sentence,"DELETE FROM %s WHERE %s;\n",argv1,argv2);
        if (mysql_query(mysql, sentence) != 0) {
            fprintf(stderr, "插入失败: %s\n", mysql_error(mysql));
        }    
        break;
    default:
        sprintf(sentence,"UPDATE %s SET %s WHERE BINARY %s;\n",argv1,argv2,argv3);
        mysql_query(mysql,sentence);
    }
    return 0;
}


int myGetpwd(usrInfo_t *usrInfo,train_t *train,threadPool_t *pThreadPool,Stack_t *tmpStack,char *cwd,char *cachePath,MYSQL *mysql){

    char *buf=NULL;
    char *argv1="fileInfo";
    char *savePtr=NULL;
    buf=train->argv;
    if(buf[0]=='/'||buf[0]=='~'){
    }
    else{
        // 相对路径
        copyStack(&usrInfo->virtulDirectory,tmpStack);
    }
    char *pathSege=NULL;
    pathSege=strtok_r(buf,"/",&savePtr);
    while (pathSege) {
        if (strcmp("..", pathSege) == 0) {
            popStack(tmpStack);
        }
        else if(strcmp(".",pathSege)==0){

        }
        else{
            // SELECT id FROM fileInfo WHERE （path=path参数，usrName=usrName参数）;
            //            char argv[64]={0};
            //            sprintf(argv,"(path=%s,usrName=%s\n)",usrInfo->cachePath,usrInfo->usrName);
            //            MySQLSentence(SELECT,mysql,"id","fileInfo",argv);
            //            MYSQL_RES *queryRes=NULL;
            //            queryRes=mysql_store_result(mysql);
            //            MYSQL_ROW row;
            //            while ((row = mysql_fetch_row(queryRes))) {
            //                printf("第一列内容: %s\n", row[0]);
            //            }
            //            char *id=row[0];
            pushStack(tmpStack, pathSege);
        }
        pathSege = strtok_r(NULL, "/", &savePtr);
    }
    if(train->command != MKDIR && train->command != PUTS){
        // 不是创建文件夹和上传的命令，检查完整路径是否正确
        sPrintfStack(tmpStack,cachePath);
        char argv4[128]={0};
        sprintf(argv4,"path='%s' and usrName='%s' and isDel=0",cachePath,usrInfo->usrName);
        MySQLSentence(SELECT,mysql,"id",argv1,argv4);
        MYSQL_ROW row;
        MYSQL_RES *queryRes=NULL;
        queryRes=mysql_store_result(mysql);
        row = mysql_fetch_row(queryRes);
        if(!row){
            return -1;
        }
        else{
            strcpy(cwd,row[0]);
        }
    }
    else{
        // mkdir 和命令检查上一级目录是否正确
        char *dirName=popStack(tmpStack);
        sPrintfStack(tmpStack,cachePath);
        char argv4[128]={0};
        sprintf(argv4,"path='%s' and usrName='%s' and isDel=0",cachePath,usrInfo->usrName);
        MySQLSentence(SELECT,mysql,"id",argv1,argv4);
        MYSQL_ROW row;
        MYSQL_RES *queryRes=NULL;
        queryRes=mysql_store_result(mysql);
        row = mysql_fetch_row(queryRes);
        if(!row){
            return -1;
        }
        strcpy(cwd,row[0]);
        pushStack(tmpStack,dirName);
        sPrintfStack(tmpStack,cachePath);
        memset(argv4,0,sizeof(argv4));
        sprintf(argv4,"path='%s' and usrName='%s' and isDel=0",cachePath,usrInfo->usrName);
        MySQLSentence(SELECT,mysql,"id",argv1,argv4);
        queryRes=mysql_store_result(mysql);
        row = mysql_fetch_row(queryRes);
        if(row){
            printf("要创建的目录或文件已存在\n");
            return -1;
        }

    }
    return 0;
}
int commandExcute(usrInfo_t *usrInfo,train_t *train,threadPool_t *pThreadPool,MYSQL *mysql){
    usrInfo->cachePath[0]='/';
    char cachePath[128]={0};
    char *argv1="fileInfo";
    char *argv2="(fileName,fileSize,parentId,usrName,type,path,isDel,hash)";
    char cwd[4096];
    Stack_t tmpStack;
    initStack(&tmpStack);
    commandType ret;
    if(myGetpwd(usrInfo,train,pThreadPool,&tmpStack,cwd,cachePath,mysql)==-1){
        ret = ERROR;
        printf("发送error=%d\n",ERROR);
        send(usrInfo->netFd,&ret,sizeof(int),0);
        return 1;
    }
    if(train->command==CD){
        // 进入指定目录
        // 相对路径 第一个字符是字母 
        // 绝对路径 第一个字符是/
        // .当前目录 ..上一级目录
        usrInfo->virtulDirectory=tmpStack;
        strcpy(usrInfo->cachePath,cachePath);
        // 当前虚拟路径
        // 真实路径
        ret=CD;
        send(usrInfo->netFd,&ret,sizeof(ret),0);

    }
    else if(train->command==PWD){
        //显示当前路径
        int len=strlen(usrInfo->cachePath);
        ret=PWD;
        send(usrInfo->netFd,&ret,sizeof(int),0);
        if(len==0){
            len=-1;
            send(usrInfo->netFd,&len,sizeof(int),0);
        }
        else{
            send(usrInfo->netFd,&len,sizeof(int),0);
            send(usrInfo->netFd,usrInfo->cachePath,len,0);
        }
    }
    else if(train->command==LS){
        //       char *id=topStack(&tmpStack);
        //       char argv4[32];
        //       sprintf(argv4,"parentId=%s",id);
        //       char argv4[128]={0};
        //       sprintf(argv4,"path='%s' and usrName='%s'",cachePath,usrInfo->usrName);
        //       MySQLSentence(SELECT,mysql,"id",argv1,argv4);
        MYSQL_ROW row;
        MYSQL_RES *queryRes=NULL;
        //       queryRes=mysql_store_result(mysql);
        //       row = mysql_fetch_row(queryRes);
        char argv5[128]={0};
        sprintf(argv5,"parentId=%s and isDel=0",cwd);
        char *argv3="fileName,type";
        MySQLSentence(SELECT,mysql,argv3,argv1,argv5);
        queryRes=mysql_store_result(mysql);
        my_ulonglong rowsCnt=0;
        rowsCnt=mysql_num_rows(queryRes);
        // 告知客户端接收结果
        ret=LS;
        send(usrInfo->netFd,&ret,sizeof(int),0);
        // 告知客户端查询结果的行数
        send(usrInfo->netFd,&rowsCnt,sizeof(rowsCnt),0);
        for(my_ulonglong i=0;i<rowsCnt;++i){
            //  告知客户端一行长度
            //  向客户端发送一行
            row = mysql_fetch_row(queryRes);
            int rowSize=strlen(row[0]);
            send(usrInfo->netFd,&rowSize,sizeof(rowSize),0);
            send(usrInfo->netFd,row[0],rowSize,0);
            rowSize=strlen(row[1]);
            send(usrInfo->netFd,&rowSize,sizeof(rowSize),0);
            send(usrInfo->netFd,row[1],rowSize,0);
        }
    }
    else if(train->command==PUTS){
        /*生成哈希值，查询缓存表 存在触发极速秒传 不存在正常上传
          将文件元数据存入文件表，将哈希值存入缓存表，将文件内容上传磁盘
          取虚拟路径栈顶元素id，查询其路径，拼接文件名得到路径
          SELECT * FROM fileCache WHERE hash=hash参数
          SELECT path FROM fileInfo WHERE id=id参数
          INSERT INTO fileInfo (fileName,fileSize,parentId,userName,type,path,isDel)VALUES ('fileName参数','fileSize参数','id参数','usrName参数','f','path参数',0); 
          INSERT INTO fileCache (hash)VALUES ('hash参数'); 
         *
         */
        ret=PUTS;
        send(usrInfo->netFd,&ret,sizeof(ret),0);
        /* char flag='0'; */
        char hash[41]={0};
        recv(usrInfo->netFd,hash,sizeof(hash),MSG_WAITALL);
        int fileSize=0;
        char fileName[32]={0};
        char *p=topStack(&tmpStack);
        strcpy(fileName,p);
        char localHash[41]={0};
        do{
            int flag=1;
            memset(localHash,0,sizeof(localHash));
            if(0==recvFileFromClient(usrInfo,hash,&fileSize)){
                printf("触发极速妙传\n");
                flag=0;
                send(usrInfo->netFd,&flag,sizeof(int),0);
                break;
            }
            getHash(hash,localHash);
            if(strcmp(hash,localHash)==0){
                flag=0;
                send(usrInfo->netFd,&flag,sizeof(int),0);
                break;
            }
            else{
                send(usrInfo->netFd,&flag,sizeof(int),0);
                char tmp[64]={0};                                                                                                                 
                sprintf(tmp,"%s.rcd",hash);
                if (remove(hash) == 0) {
                } else {
                    perror("删除文件失败");
                }
                if (remove(tmp) == 0) {
                } else {
                    perror("删除文件失败");
                }
            }

        }while(1);
        //     popStack(&tmpStack);
        //     char parentPath[128]={0};
        //     sPrintfStack(&tmpStack,parentPath);
        //     /* char *parentId=topStack(&tmpStack); */
        char argv4[256]={0};
        //     sprintf(argv4,"path='%s' and usrName='%s'",parentPath,usrInfo->usrName);
        //     MySQLSentence(SELECT,mysql,"id",argv1,argv4);
        //     MYSQL_RES *queryRes=NULL;
        //     queryRes=mysql_store_result(mysql);
        //     MYSQL_ROW row;
        //     row = mysql_fetch_row(queryRes);
        sprintf(argv4,"('%s',%d,'%s','%s','%s','%s',%s,'%s')",fileName,fileSize,cwd,usrInfo->usrName,"f",cachePath,"0",hash);
        MySQLSentence(INSERT,mysql,argv1,argv2,argv4);
        /* ret=MKDIR; */
        /* send(usrInfo->netFd,&ret,sizeof(int),0); */
        printf("文件上传成功\n");
    }
    else if(train->command==GETS){
        printf("客户端下载文件\n");
        ret=GETS;
        send(usrInfo->netFd,&ret,sizeof(int),0);
        char argv4[32]={0};
        sprintf(argv4,"id=%s and isDel=0",cwd);
        MySQLSentence(SELECT,mysql,"hash",argv1,argv4);
        MYSQL_RES *queryRes=NULL;
        queryRes=mysql_store_result(mysql);
        MYSQL_ROW row;
        row = mysql_fetch_row(queryRes);
        int hashLen=strlen(row[0]);
        send(usrInfo->netFd,&hashLen,sizeof(int),0);
        send(usrInfo->netFd,row[0],hashLen,0);
        printf("发送的长度%d %s\n",hashLen,row[0]);
        do{
            sendFileToClient(usrInfo,row[0]);
            int flag=1;
            recv(usrInfo->netFd,&flag,sizeof(int),MSG_WAITALL);
            printf("收到的flag=%d\n",flag);
        }while(flag);
    }
    else if(train->command==REMOVE){
        // 删除文件 
        /* char *id=topStack(&tmpStack); */
        char argv3[32]={0};
        sprintf(argv3,"id=%s",cwd);
        MySQLSentence(UPDATE,mysql,argv1,"isDel=1",argv3);
        ret=REMOVE;
        /* send(usrInfo->netFd,&ret,sizeof(int),0); */
    }
    else if(train->command==RMDIR){
        // 删除目录 检查父节点为该id的返回结果为空 更改isDel标志位
        /* char *id=topStack(&tmpStack); */
        char argv4[128]={0};
        //        sprintf(argv4,"path='%s' and usrName='%s'",cachePath,usrInfo->usrName);
        //        MySQLSentence(SELECT,mysql,"id",argv1,argv4);
        MYSQL_ROW row;
        MYSQL_RES *queryRes=NULL;
        //        queryRes=mysql_store_result(mysql);
        //        row = mysql_fetch_row(queryRes);
        //        char id[8]={0};
        //        strcpy(id,row[0]);
        char argv5[128]={0};
        sprintf(argv5,"parentId=%s and isDel=0",cwd);
        MySQLSentence(SELECT,mysql,"id",argv1,argv5);
        queryRes=mysql_store_result(mysql);
        if((row = mysql_fetch_row(queryRes))){
            // 非空目录
        }
        else{
            char argv4[32];
            sprintf(argv4,"id=%s",cwd);
            MySQLSentence(DELETE,mysql,argv1,argv4,NULL);
        }
        ret=RMDIR;
        send(usrInfo->netFd,&ret,sizeof(int),0);
    }
    else if(train->command==MKDIR){
        /*取虚拟路径栈顶元素id，查询其路径，拼接目录名得到路径
          将文件元数据存入文件表
          INSERT INTO fileInfo (fileName,parentId,userName,type,path,isDel)VALUES ('fileName参数','id参数','usrName参数','d','path参数',0);
          sprintf(argv,"('%s','%s','%s','%s','%s','%s','%d')",文件名参数
          INSERT into fileinfo (fileName,parentId,userName,type,path,isDel) values argv
          rmdir
          取虚拟路径栈顶元素id，更改isDel标志位
          UPDATAE　fileInfo SET isDel=1 WHERE id=id参数 
          */
        char fileName[32]={0};
        char *p=topStack(&tmpStack);
        memcpy(fileName,p,strlen(p));
        //       popStack(&tmpStack);
        //       char parentPath[128]={0};
        //       sPrintfStack(&tmpStack,parentPath);
        //       /* char *parentId=topStack(&tmpStack); */
        char argv3[256]={0};
        //       sprintf(argv3,"path='%s' and usrName='%s'",parentPath,usrInfo->usrName);
        //       MySQLSentence(SELECT,mysql,"id",argv1,argv3);
        //       MYSQL_RES *queryRes=NULL;
        //       queryRes=mysql_store_result(mysql);
        //       MYSQL_ROW row;
        //       row = mysql_fetch_row(queryRes);
        sprintf(argv3,"('%s',%d,'%s','%s','%s','%s',%s,'%s')",fileName,0,cwd,usrInfo->usrName,"d",cachePath,"0",(char *)NULL);
        MySQLSentence(INSERT,mysql,argv1,argv2,argv3);
        ret=MKDIR;
        /* send(usrInfo->netFd,&ret,sizeof(int),0); */
        printf("目录创建成功\n");
    }
    //    else if(train->command==TREE){
    //        // 打印根目录名称
    //        printf("%s\n", cachePath);
    //
    //        // 从根目录开始深度优先遍历打印目录树, 初始-打印4个
    //        DFS_print(cwd, 4);
    //        printf("\n%d directories, %d files\n", dirs, files);
    //        dirs=0;
    //        files=0;
    //    }
    return 0;
}
